package shm;

import org.apache.tomcat.jni.Global;
import org.apache.tomcat.jni.Pool;
import org.apache.tomcat.jni.Shm;
import org.apache.tomcat.jni.Status;

import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;

/**
 * License: Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0.html)
 * <p/>
 * Author: Ashwin Jayaprakash
 * <p/>
 * Email: ashwin.jayaprakash@gmail.com
 * <p/>
 * Web: http://www.ashwinjayaprakash.com
 */
public class ShmReader extends ShmCommon {
    public ShmReader() {
    }

    public void test() throws Exception {
        long poolHandle = Pool.create(0);
        sout("Attached to Pool " + poolHandle);

        long shmHandle = Shm.attach(NAME_SHM, poolHandle);
        sout("Attached to Shm " + NAME_SHM);

        try {
            long mutexHandle = Global.childInit(NAME_MUTEX, poolHandle);
            sout("Attached to Mutex " + NAME_MUTEX);

            for (; ; ) {
                sout("Trying lock Mutex " + mutexHandle + " @ " + new Date());
                int lockStatus = Global.trylock(mutexHandle);

                if (Status.APR_STATUS_IS_EBUSY(lockStatus)) {
                    sout("Try lock failed on Mutex " + mutexHandle + " @ " + new Date());

                    sout("Retrying in 10 secs");
                    LockSupport.parkNanos(Thread.currentThread(), TimeUnit.NANOSECONDS.convert(10, TimeUnit.SECONDS));
                    continue;
                }

                sout("Locked Mutex " + mutexHandle + " @ " + new Date());
                break;
            }

            try {
                ByteBuffer bb = Shm.buffer(shmHandle);
                sout(bb.toString());

                int numChars = bb.getInt();

                CharBuffer cb = bb.asCharBuffer();
                char[] chars = new char[numChars];
                cb.get(chars);

                sout("Read message [" + new String(chars) + "]");
            }
            finally {
                Global.unlock(mutexHandle);
                sout("Unlocked Mutex " + mutexHandle + " @ " + new Date());
            }
        }
        finally {
            Shm.detach(shmHandle);
            sout("Detached Shm " + shmHandle + " @ " + new Date());
        }

        Pool.clear(poolHandle);
        sout("Cleared Pool " + poolHandle);

        sout("Exiting..." + getClass().getName());
    }

    public static void main(String[] args) throws Exception {
        new ShmReader().test();
    }
}
